#include "media_osd.h"

#include <inttypes.h>
#include <string.h>
#include <sys/time.h>
#include <vector>
#include <cassert>
#include <memory>
#include "utils_log.h"
#include "common_config_manager.h"
#include "media_speak.h"
#include "hal_audio.h"
#include <fstream>
#include <unistd.h>

namespace El {
namespace Media {

Speak &Speak::GetInstance()
{
    static Speak instance;
    return instance;
}

Speak::Speak()
{
    EL_INFO("Media Speak initialized.");
}

Speak::~Speak() {}

bool Speak::Start()
{
    EL_INFO("Starting Speak service...");

    // 获取扬声器音量配置
    auto speaker_config = El::Common::ConfigManager::GetInstance().GetConfig("/audio/volume");
    if (speaker_config.is_null() || !speaker_config.contains("speaker_volume")) {
        EL_WARN("Speaker volume configuration not found or incomplete. Using default HAL settings.");
        // 可以选择不设置，让 HAL 使用其默认值，或者设置一个预定义的应用级默认值
    } else {
        int32_t volume = speaker_config.value("speaker_volume", 80); // 如果没有则使用默认值80
        if (volume < 0 || volume > 100) {
            EL_WARN("Invalid speaker volume value ({}) in config. Clamping to 0-100 range.", volume);
            volume = std::max(0, std::min(100, volume)); // 确保音量在0-100之间
        }
        EL_INFO("Setting speaker volume from config: {}", volume);
        if (!SetVolume(volume)) {
            EL_ERROR("Failed to set speaker volume from config.");
            // 根据需求决定是否因为音量设置失败而导致 Start 失败
        }
    }

    // 获取扬声器静音配置 (如果后续需要实现)
    /*
    if (speaker_config.is_null() || !speaker_config.contains("speaker_mute")) {
        EL_WARN("Speaker mute configuration not found. Using default HAL settings.");
    } else {
        bool mute = speaker_config.value("speaker_mute", false);
        EL_INFO("Setting speaker mute from config: {}", mute);
        // int32_t ret = Hal_Ao_SetMute(0, mute ? true : false, HAL_AUDIO_FADE_RATE_DEFAULT);
        // if (ret != 0) {
        //     EL_ERROR("Hal_Ao_SetMute failed with error code: {}", ret);
        // }
    }
    */

    // TODO: 获取并设置麦克风音量和静音状态 (如果需要)
    // auto mic_config = El::Common::ConfigManager::GetInstance().GetConfig("/audio/volume");
    // if (mic_config.is_null() || !mic_config.contains("mic_volume")) { ... }
    // Hal_Ai_SetVol(...);
    // Hal_Ai_SetMute(...);

    EL_INFO("Speak service started successfully.");
    return true;
}

bool Speak::StartFilePlay(const char *path, int32_t repeatCount, const HAL_ADEC_COM_CONFIG_S *adecConfig)
{
    if (isPlaying_) {
        EL_WARN("Playback already in progress. Stopping previous playback first.");
        Stop();
    }
    EL_INFO("Start file playback for: {}, repeat count: {}", path, repeatCount);

    audioFile_.open(path, std::ios::binary);
    if (!audioFile_.is_open()) {
        EL_ERROR("Failed to open audio file: {}", path);
        return false;
    }
    currentFilePath_ = path;
    repeatCount_ = repeatCount;
    initialRepeatCount_ = repeatCount; // 保存初始重复次数，用于循环播放

    // 初始化音频数据队列
    audioDataQueue_ = std::make_unique<El::Utils::BlockingQueue<std::vector<char>>>("audio_data_queue",
                                                                                    kDefaultAudioStreamQueueCapacity);

    // 设置音频解码器配置
    HAL_ADEC_COM_CONFIG_S defaultConfig = {};
    if (adecConfig == nullptr) {
        // 使用默认配置
        defaultConfig.u32SampleRate = HAL_AUDIO_SAMPLE_RATE_48000;
        defaultConfig.eType = HAL_AUDIO_TYPE_MP3;
        defaultConfig.u8ChanNum = 1;
        defaultConfig.u8Vol = 6;
        adecConfig = &defaultConfig;
    }

    int32_t ret = Hal_Adec_Start(0, const_cast<HAL_ADEC_COM_CONFIG_S *>(adecConfig));
    if (ret != HAL_SUCCESS) {
        EL_ERROR("Hal_Adec_Start failed with error code: {}", ret);
        audioFile_.close();
        currentFilePath_.clear();
        audioDataQueue_.reset();
        return false;
    }

    // 设置源类型为文件
    sourceType_ = PlaySourceType::FILE;
    isPlaying_ = true;

    // 启动文件读取线程
    fileReadThread_ = std::make_unique<std::thread>(&Speak::ReadFileToQueue, this);

    // 启动统一播放线程
    playbackThread_ = std::make_unique<std::thread>(&Speak::PlayThread, this);
    return true;
}

void Speak::Stop()
{
    if (!isPlaying_) {
        EL_WARN("No playback in progress to stop.");
        return;
    }

    EL_INFO("Stopping playback. Source type: {}", static_cast<int>(sourceType_.load()));
    isPlaying_ = false;

    // 停止队列操作
    if (audioDataQueue_) {
        audioDataQueue_->SetActive(false);
    }

    // 等待文件读取线程结束（如果有）
    if (fileReadThread_ && fileReadThread_->joinable()) {
        fileReadThread_->join();
        fileReadThread_.reset();
    }

    // 等待播放线程结束
    if (playbackThread_ && playbackThread_->joinable()) {
        playbackThread_->join();
        playbackThread_.reset();
    }

    // 停止解码器
    int32_t ret = Hal_Adec_Stop(0, 1000);
    if (ret != HAL_SUCCESS) {
        EL_WARN("Hal_Adec_Stop failed with error code: {} (continuing cleanup)", ret);
    }

    // 清理文件相关资源
    if (audioFile_.is_open()) {
        audioFile_.close();
    }
    currentFilePath_.clear();

    // 清理队列并重置
    if (audioDataQueue_) {
        audioDataQueue_->Clear();
        audioDataQueue_.reset();
    }

    // 重置源类型
    sourceType_ = PlaySourceType::NONE;

    EL_INFO("Playback stopped.");
}

void Speak::ReadFileToQueue()
{
    EL_DEBUG("File read thread started for file: {}", currentFilePath_);
    std::vector<char> buffer(kAudioBufferSize);
    bool hasDataToProcess = false;
    size_t bytesRead = 0;

    while (isPlaying_ && sourceType_ == PlaySourceType::FILE) {
        // 只有当没有待处理数据时才从文件读取
        if (!hasDataToProcess) {
            // 从文件读取数据
            audioFile_.read(buffer.data(), kAudioBufferSize);
            bytesRead = audioFile_.gcount();

            if (bytesRead > 0) {
                hasDataToProcess = true;
            } else if (audioFile_.eof()) {
                // 处理文件结束情况
                EL_DEBUG("End of audio file reached: {}", currentFilePath_);

                // 处理循环播放逻辑
                if (initialRepeatCount_ == 0) {
                    // 无限循环模式
                    EL_DEBUG("Infinite loop mode: restarting audio file: {}", currentFilePath_);
                    audioFile_.clear();                 // 清除 EOF 标志
                    audioFile_.seekg(0, std::ios::beg); // 重置到文件开头
                    continue;
                } else if (repeatCount_ > 1) {
                    // 还有剩余重复次数
                    repeatCount_--;
                    EL_DEBUG("Repeating audio file: {}. Remaining repeats: {}", currentFilePath_, repeatCount_);
                    audioFile_.clear();                 // 清除 EOF 标志
                    audioFile_.seekg(0, std::ios::beg); // 重置到文件开头
                    continue;
                } else {
                    // 重复播放完成
                    EL_DEBUG("All repeats completed for audio file: {}", currentFilePath_);
                    break;
                }
            } else if (audioFile_.fail() && !audioFile_.eof()) {
                EL_ERROR("Error reading audio file: {}. Stopping file reading.", currentFilePath_);
                break;
            }
        }

        // 如果有数据需要处理，尝试推送到队列
        if (hasDataToProcess) {
            std::vector<char> audioChunk(buffer.data(), buffer.data() + bytesRead);

            // 尝试推送数据到队列
            if (audioDataQueue_->Push(std::move(audioChunk), 100)) {
                // 推送成功，标记没有待处理数据
                hasDataToProcess = false;
            } else if (!isPlaying_) {
                // 播放已停止，退出循环
                break;
            } else {
                // 队列满，稍后再试
                EL_TRACE("Failed to push file data to audio queue, retrying...");
            }
        }
    }

    EL_INFO("File read thread finished for file: {}", currentFilePath_);
}

void Speak::PlayThread()
{
    EL_DEBUG("Unified playback thread started for channel {}", 0);

    while (isPlaying_) {
        // 从队列中读取音频数据
        std::vector<char> audioChunk = audioDataQueue_->Pop(100); // 100ms超时

        if (!audioChunk.empty()) {
            // 发送数据到解码器
            int32_t ret = Hal_Adec_SendData(0, reinterpret_cast<uint8_t *>(audioChunk.data()),
                                            static_cast<uint32_t>(audioChunk.size()),true);
            if (ret != HAL_SUCCESS) {
                EL_ERROR("Hal_Adec_SendData failed with error code: {}. Continuing playback.", ret);
                // 这里不退出，继续处理队列中的数据
            }
        }

        // 如果播放已停止且队列为空，退出线程
        if (!isPlaying_ && (audioDataQueue_ == nullptr || audioDataQueue_->Empty())) {
            EL_INFO("Playback stopped and queue is empty, exiting playback thread");
            break;
        }
    }

    EL_INFO("Unified playback thread finished for channel {}", 0);
}

bool Speak::StartStreamPlay(const HAL_ADEC_COM_CONFIG_S &adecConfig)
{
    if (isPlaying_) {
        EL_WARN("Playback already in progress. Stopping previous playback first.");
        Stop();
    }
    EL_INFO("Starting stream playback.");

    // 创建音频数据队列
    audioDataQueue_ = std::make_unique<El::Utils::BlockingQueue<std::vector<char>>>("audio_data_queue",
                                                                                    kDefaultAudioStreamQueueCapacity);

    HAL_ADEC_COM_CONFIG_S adecConfigCopy = adecConfig; // 修复类型
    int32_t ret = Hal_Adec_Start(0, &adecConfigCopy);  // 传入非常量指针
    if (ret != HAL_SUCCESS) {
        EL_ERROR("Hal_Adec_Start failed with error code: {}", ret);
        audioDataQueue_.reset();
        return false;
    }

    // 设置源类型为流
    sourceType_ = PlaySourceType::STREAM;
    isPlaying_ = true;

    // 启动统一播放线程
    playbackThread_ = std::make_unique<std::thread>(&Speak::PlayThread, this);
    EL_INFO("Stream playback started.");
    return true;
}

bool Speak::PushAudioData(const char *data, size_t size, bool useBlockingMode)
{
    if (!isPlaying_ || sourceType_ != PlaySourceType::STREAM) {
        EL_WARN("Playback is not active or not in streaming mode.");
        return false;
    }
    if (data == nullptr || size == 0) {
        EL_WARN("Invalid audio data provided.");
        return false;
    }

    // 阻塞模式：直接调用HAL接口发送数据
    if (useBlockingMode) {
        int32_t ret = Hal_Adec_SendData(0, const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(data)),
                                        static_cast<uint32_t>(size), true);
        if (ret != HAL_SUCCESS) {
            EL_ERROR("Hal_Adec_SendData (blocking mode) failed with error code: {}", ret);
            return false;
        }
        return true;
    }

    // 非阻塞模式：通过队列异步发送（使用固定100ms超时）
    if (!audioDataQueue_) {
        EL_WARN("Audio data queue not initialized.");
        return false;
    }

    std::vector<char> audioChunk(data, data + size);
    bool pushed = audioDataQueue_->Push(std::move(audioChunk), 100);
    if (!pushed) {
        EL_WARN("Failed to push audio data to queue, possibly timeout or queue is inactive.");
    }
    return pushed;
}

bool Speak::SetVolume(int32_t volume)
{
    EL_DEBUG("Setting audio output volume to: {}", volume);
    if (volume < 0 || volume > 100) {
        EL_WARN("Invalid speaker volume value ({}) requested. Clamping to 0-100 range.", volume);
        volume = std::max(0, std::min(100, volume)); // 确保音量在0-100之间
    }

    int32_t ret = Hal_Ao_SetVol(static_cast<int32_t>(volume));
    if (ret != HAL_SUCCESS) {
        EL_ERROR("Hal_Ao_SetVol failed with error code: {}", ret);
        return false;
    }

    // 保存到配置
    nlohmann::json audio_volume_config = El::Common::ConfigManager::GetInstance().GetConfig("/audio/volume");
    if (audio_volume_config.is_null()) {
        // 如果配置不存在，创建一个新的
        audio_volume_config = nlohmann::json::object();
    }
    audio_volume_config["speaker_volume"] = volume;
    // 保留可能存在的其他音频配置项，如静音状态
    // if (!audio_volume_config.contains("speaker_mute")) {
    //     audio_volume_config["speaker_mute"] = false; // Or read from HAL if possible
    // }
    // if (!audio_volume_config.contains("mic_volume")) {
    //     audio_volume_config["mic_volume"] = 80; // Default or read from HAL
    // }
    // if (!audio_volume_config.contains("mic_mute")) {
    //     audio_volume_config["mic_mute"] = false; // Default or read from HAL
    // }

    if (!El::Common::ConfigManager::GetInstance().SetConfig("/audio/volume", audio_volume_config)) {
        EL_ERROR("Failed to save speaker volume to configuration.");
        // 根据需求，这里可以决定是否因为配置保存失败而返回 false
    } else {
        EL_INFO("Speaker volume set to {} and saved to configuration.", volume);
    }

    return true;
}

int32_t Speak::GetVolume() const
{
    // 优先从配置中读取当前音量
    auto audio_volume_config = El::Common::ConfigManager::GetInstance().GetConfig("/audio/volume");
    if (!audio_volume_config.is_null() && audio_volume_config.contains("speaker_volume") &&
        audio_volume_config["speaker_volume"].is_number()) {
        int32_t volume = audio_volume_config["speaker_volume"].get<int32_t>();
        if (volume >= 0 && volume <= 100) {
            EL_DEBUG("GetVolume from config: {}", volume);
            return volume;
        }
        EL_WARN("Invalid volume value ({}) in config. Will try to get from HAL.", volume);
    }

    // 如果配置中没有或无效，尝试从 HAL 获取 (如果 HAL 支持)
    // 注意：Hal_Ao_GetVol 并非标准接口，此处为示例，你需要替换为实际的 HAL 调用
    // int32_t hal_volume = -1; // 假设的 HAL 返回值
    // int32_t ret = Hal_Ao_GetVol(&hal_volume); // 假设的 HAL 获取音量函数
    // if (ret == 0 && hal_volume >= 0 && hal_volume <= 100) {
    //     EL_DEBUG("GetVolume from HAL: {}", hal_volume);
    //     return static_cast<int32_t>(hal_volume);
    // }
    // EL_WARN("Failed to get volume from HAL or HAL value is invalid. Returning default.");

    // 如果都失败，返回一个默认值
    EL_DEBUG("GetVolume returning default value (80).");
    return 80; // 默认音量值
}

std::string Speak::GetCurrentFilePath() const
{
    if (!isPlaying_ || sourceType_ != PlaySourceType::FILE) {
        return "";
    }

    // 这里返回当前播放的文件路径
    return currentFilePath_;
}

} // namespace Media
} // namespace El
